<?php

namespace chain\Db;
use PDO;

class Db implements DbInterface{
    private $conn;
    private static $instance;

    /**
     * Db constructor.
     * @param $config
     */
    private function __construct($config)
    {
        try{
            $dsn = "mysql:host={$config['host']};dbname={$config['dbname']}";
            $opt = array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8",PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
            $this->conn = new PDO($dsn,$config['usrname'],$config['password'],$opt);
        }catch (PDOException $e){
            echo $e->getMessage();
        }
        return $this->conn;
    }

    private function __clone(){

    }

    /**
     * @param $conn
     * @return Db|PDO|null 返回DB实例 其中conn属性包含数据库连接
     */
    public static function getInstance($config){
        if(!(self::$instance instanceof self)){
            self::$instance = new self($config);
        }
        return self::$instance;
    }

    public function check(){
        if(!(self::$instance instanceof self)){
            exit("还没有实例化类");
        }
    }

    /**
     * @param $sql
     * @return array 针对select 可能有返回数据内容
     */
    public function queryString($sql){
        //echo "<br>" . $sql . "<br>";
        $this->check();
        try{
            $stmt = $this->conn->prepare($sql);
            $stmt->execute();
            $res = $stmt->fetchAll(PDO::FETCH_ASSOC);
            return $res;
        }catch (PDOException $e){
            echo $e->getMessage();
        }
    }

    /**
     * @param $sql
     * @return int|string 针对update、delele、insert 这种返回受影响的行数类型
     */
    public function query($sql,$replaceData = null){
        //echo "<br>" . $sql . "<br>";
        $this->check();
        try{
            $stmt = $this->conn->prepare($sql);
            if(!empty($replaceData)){
                $stmt->execute($replaceData);
            }else{
                $stmt->execute();
            }
            if(!$stmt->rowCount()){
                return "获取受影响函数失败,操作失败";
            }
            return $stmt->rowCount();
        }catch (PDOException $e){
            echo $e->getMessage();
        }
    }


    /**
     * @param array $v
     * @return array|void
     */
    public function cleanValue($v = array()){
        if(empty($v)){
            return;
        }
        //处理sql 防注入
        $tmp = array();

        foreach ($v as $key => $value){
            if(is_scalar($value)){
                $tmp_key = ":" . $key;
                $tmp[$tmp_key] = addslashes($value);
            }else{
                exit("值不能是数组或者对象<<");
            }

        }
        return $tmp;
    }

    /**
     * @param $table
     * @param $data
     * @return int|string
     */
    public function insert($table,$data){
        $sql = "insert into {$table}";
        $keys = array_keys($data);
        $arrKey = $arrValue = array();
        foreach($keys as $v){
            $arrKey[] = $v;
            $arrValue[] = ":" . $v;
        }
        $sql .= "(" . implode(",",$arrKey) . ")" . " values(" . implode(",",$arrValue) . ")";
        $value = $this->cleanValue($data);
        return $this->query($sql,$value);
    }

    /**
     * @param $table
     * @param array $where
     * @return int|string
     */
    //where还需要特殊处理
    public function delete($table,$where = array()){
        if(empty($where)){
            exit("删除-条件不能为空");
        }
        $sql = "delete from {$table}";
        $tmp_where = $this->getWhereStatement($where);
        $sql .= $tmp_where;
        return $this->query($sql);
    }

    /**
     * @param $where 二维数组
     * @return string
     */
    public function getWhereStatement($where){
        $tmp_where = " where ";
        foreach($where as $key => $value){
            if(is_string($value[2])){
                $tmp_value = '"' . $value[2] . '"';
            }
            if(is_integer($value[2])){
                $tmp_value = intval($value[2]);
            }
            $tmp_where .= $value[0] . $value[1]  . $tmp_value . " and ";
        }
        $tmp_where = substr($tmp_where,0,-4);
        return $tmp_where;
    }

    /**
     * @param $table
     * @param $data
     * @param $where
     * @return int|string
     */
    public function update($table,$data = array(),$where = array()){
        if(empty($data)){
            exit("更新数据没有提供");
        }
        $sql = "update {$table} set ";
        $keys = array_keys($data);
        $sets = "";
        foreach($keys as $v){
            $sets .= $v . "=:" . $v . ",";
        }
        $sets = rtrim($sets,",");
        $sql .= $sets;
        $tmp_where = $this->getWhereStatement($where);
        $sql .= $tmp_where;
        return $this->query($sql,$this->cleanValue($data));
    }

    /**
     * @param $table
     * @param $field
     * @param $where
     */
    public function select($table,$field = array(),$where = array()){
        $sql = "select ";
        $selected = "";
        if(empty($field)){
            $selected = "*";
        }else{
            $selected = implode(",",$field);
        }
        $sql .= $selected;
        $sql .= " from {$table}";
        if(empty($where)){
            return $this->queryString($sql);
        }else{
            $tmp_where = $this->getWhereStatement($where);
            $sql .= $tmp_where;
            return $this->queryString($sql);
        }

    }





}




?>







